import { HttpException, Injectable } from '@nestjs/common'
import { MenuEntity } from './entities/menu.entity'
import { DeepPartial, EntityManager, In, Repository } from 'typeorm'
import { InjectRepository } from "@nestjs/typeorm"
import { formatFee, getCurrentTime, handleTimeRange, robotMsg, sendWeComMsg, updateFields } from "@/utils/index"
import { CreateMenuDto } from './dto/create-menu.dto'
import { UpdateMenuDto } from './dto/update-menu.dto'
import { delMenuDto } from './dto/del-menu.dto'
import { OrderEntity } from '../order/entities/order.entity'
import { CreateOrderDto } from '../order/dto/order.dto'
import { OrderItemEntity } from '../order/entities/order-item.entity'
import { ListMenuDto } from './dto/list-menu.dto'
import { UserEntity } from '../user/entities/user.entity'
// import dayjs from 'dayjs'
import { MenuDetailEntity } from '../menuDetail/entities/menuDetail.entity'
import { WalletLogService } from '../points/points.service'
import { walletType } from '@/mock'
export interface MenuRo {
  total: number
  entries: MenuEntity[]
}

@Injectable()
export class MenuService {
  constructor(
    @InjectRepository(MenuEntity) // 注入 MenuEntity 的 Repository
    private readonly menuRepository: Repository<MenuEntity>,
    @InjectRepository(OrderEntity) // 注入 OrderEntity 的 Repository
    private readonly orderRepository: Repository<OrderEntity>,
    @InjectRepository(OrderItemEntity) // 注入 OrderItemEntity 的 Repository
    private readonly orderItemRepository: Repository<OrderItemEntity>,
    @InjectRepository(UserEntity) // 注入 UserEntity 的 Repository
    private userRepository: Repository<UserEntity>,
    @InjectRepository(MenuDetailEntity) // 注入 MenuDetailEntity 的 Repository
    private menuDetailRepository: Repository<MenuDetailEntity>,
    private entityManager: EntityManager,
    private walletLogService: WalletLogService,
  ) { }

  // 新增菜品
  async create(data: CreateMenuDto & { user_id: number }): Promise<MenuEntity> {
    const exist = await this.menuRepository.findOne({
      where: { name: data.name, user_id: data.user_id }
    })

    if (exist) throw new HttpException('该菜品已存在', 409)
    const menu = await this.menuRepository.save({
      name: data.name,
      fee: data.fee,
      photo_url: data.photo_url,
      type: data.type,
      user_id: data.user_id,
      is_new: 1,
      create_time: Math.floor(Date.now() / 1000),
      update_time: Math.floor(Date.now() / 1000)
    })

    // 保存详情信息到menu_detail表
    await this.menuDetailRepository.save({
      menu_id: menu.id,
      description: data.description,
      ingredients: data.ingredients
    })

    return menu
  }

  // 获取菜品列表
  async list(query: ListMenuDto): Promise<MenuRo> {
    const qb = await this.menuRepository.createQueryBuilder('menu')
    qb.orderBy('menu.create_time', 'DESC')
    qb.andWhere('menu.is_del = :is_del', { is_del: 0 })
    // qb.andWhere('menu.user_id = :user_id', { user_id: query.user_id })

    // 允许查询的字段白名单
    const validFields = ['name', 'type', 'create_time', 'update_time']

    const { page = 1, pageSize = 10, start, end, updateStart, updateEnd, ...params } = query
    Object.entries(params).forEach(([key, value]) => {
      if (!['', undefined, null].includes(value as any) && validFields.includes(key)) {
        if (key === 'name') {
          qb.andWhere(`menu.${key} LIKE :${key}`, { [key]: `%${value}%` })
        } else {
          qb.andWhere(`menu.${key} = :${key}`, { [key]: key === 'type' ? Number(value) : value })
        }
      }
    })

    handleTimeRange(qb, 'menu', 'create_time', 'start', 'end', query)
    handleTimeRange(qb, 'menu', 'update_time', 'updateStart', 'updateEnd', query)
    const pageNum = Math.max(1, Number(page) || 1)
    const pageSizeNum = Math.min(100, Math.max(1, Number(pageSize) || 10))
    const total = await qb.getCount()
    const temp = (await qb.skip((pageNum - 1) * pageSizeNum).take(pageSizeNum).getMany()).map(({ is_del, user_id, ...rest }) => rest)

    // await robotMsg('最新的测试消息喔~')
    return {
      entries: temp.map(({ create_time, update_time, sales, type, ...rest }) => rest),
      total
    }
  }

  // 更新菜品
  async update(data: UpdateMenuDto & { user_id: number }) {
    // 原数据
    const original = await this.menuRepository.findOne({
      where: { id: data.id, user_id: data.user_id },
      relations: ['detail']
    })
    if (!original) throw new HttpException('菜品不存在', 404)

    const validUpdate = updateFields(data, ['name', 'fee', 'type', 'photo_url', 'description', 'ingredients'])
    const finalData = {
      ...original,
      ...validUpdate,
      update_time: Math.floor(Date.now() / 1000)
    }

    // 更新详情
    if (data.description !== undefined || data.ingredients !== undefined) {
      await this.menuDetailRepository.upsert(
        {
          menu_id: data.id,
          description: data.description ?? original.detail?.description ?? '',
          ingredients: data.ingredients ?? original.detail?.ingredients ?? ''
        },
        ['menu_id']
      )
    }
    return this.menuRepository.save(finalData as DeepPartial<MenuEntity>)
  }

  // 删除菜品
  async delete(data: delMenuDto): Promise<MenuEntity> {
    const temp = await this.menuRepository.findOne({ where: { id: data.id } })
    if (!temp) throw new HttpException('该菜品不存在', 409)
    temp.is_del = 1
    await this.menuRepository.save(temp)
    return temp
  }

  async handleOrder(data: CreateOrderDto, userId: number): Promise<OrderEntity> {
    if (data.order_id) {
      if (typeof (data.order_id) !== 'number') throw new HttpException('订单ID为number类型', 400)
      if (!Number.isInteger(data.order_id) || data.order_id <= 0) throw new HttpException('订单ID必须是正整数', 400)
      // 有order_id → 更新订单状态
      return this.confirmPayment(data.order_id, userId, data.status)
    } else {
      // 新增订单
      return this.placeOrder(data, userId)
    }
  }

  // 下单（余额扣除，事务处理）
  async placeOrder(data: CreateOrderDto, userId: number): Promise<OrderEntity> {
    if (!data.items || !data.items.length) {
      throw new HttpException('订单不能为空，请至少选择一个菜品', 400)
    }
    data.items.forEach((item, index) => {
      if (!item.menu_id || item.menu_id <= 0) {
        throw new HttpException(`第${index + 1}个订单项的菜品ID无效`, 400)
      }
      if (!item.quantity || item.quantity <= 0 || !Number.isInteger(item.quantity)) {
        throw new HttpException(`第${index + 1}个订单项的数量必须是正整数`, 400)
      }
    })

    // 事务处理所有操作（订单创建 + 订单项创建 + 积分扣除）
    return this.entityManager.transaction(async (manager) => {
      // 查询用户信息（校验饭币是否足够）
      const user = await manager.findOne(UserEntity, { where: { id: userId } })
      if (!user) {
        throw new HttpException('当前用户不存在，无法下单', 404)
      }

      const menuIds = data.items.map(item => item.menu_id)
      const menuItems = await manager.find(MenuEntity, {
        where: { id: In(menuIds), is_del: 0 },
      })

      if (menuItems.length !== menuIds.length) {
        throw new HttpException('部分菜品不存在或已删除，无法下单', 404)
      }

      // 计算订单总金额
      const totalFee = data.items.reduce((total, item) => {
        const menuItem = menuItems.find(k => k.id === item.menu_id)
        return total + (menuItem?.fee || 0) * item.quantity
      }, 0)
      if (totalFee <= 0) {
        throw new HttpException('订单总金额无效，无法下单', 400)
      }

      // 校验用户余额是否足够
      const userBalance = user.balance || 0
      if (userBalance < totalFee) {
        throw new HttpException('钱包余额不足', 400)
      }

      // 创建订单
      const order = new OrderEntity()
      order.dining_method = data.dining_method
      order.remark = data.remark ?? ''
      order.status = data.status ?? 0
      order.user_id = userId
      order.total_fee = totalFee
      order.create_time = Math.floor(Date.now() / 1000)
      const savedOrder = await manager.save(OrderEntity, order)

      // 创建订单条目
      const itemQuantityMap = new Map(
        data.items.map(item => [item.menu_id, item.quantity])
      )
      const orderItems = menuItems.map(menuItem => {
        const orderItem = new OrderItemEntity()
        orderItem.order = savedOrder // 关联已保存的订单
        orderItem.menu_id = menuItem.id
        orderItem.menu_name = menuItem.name
        orderItem.menu_fee = menuItem.fee
        orderItem.quantity = itemQuantityMap.get(menuItem.id) || 0
        orderItem.menu_photo = menuItem.photo_url
        return orderItem
      })
      await manager.save(OrderItemEntity, orderItems)

      // 扣除用户余额
      // user.balance = userBalance - totalFee // 余额 = 原余额 - 订单总金额
      user.update_time = Math.floor(Date.now() / 1000)
      // 记录钱包日志（点餐扣除）
      await this.walletLogService.createTransaction(userId, walletType.ORDER, totalFee)
      await manager.save(UserEntity, user)

      // 推送企微消息
      const nickname = user.nickname || `用户${userId}`
      const remarkText = savedOrder.remark ? `\n📝 备注：${savedOrder.remark}` : ''
      const orderStr = orderItems.map(item => `${item.menu_name} x${item.quantity}`).join('、')
      const currentTime = getCurrentTime()
      const dinnerType = { 1: '堂食', 2: '外带' }
      await sendWeComMsg(
        `${currentTime} ${nickname}创建新订单\n` +
        `🧾 订单ID: ${savedOrder.id}\n` +
        `状态：${savedOrder.status === 0 ? '⏳ 待付款' : '✅ 已付款'}\n` +
        `用餐方式：${dinnerType[savedOrder.dining_method]}\n` +
        `🍲 菜品：${orderStr}\n` +
        `💰 金额：${savedOrder.total_fee}\n` +
        `💳 用户剩余余额：${formatFee(user.balance, savedOrder.total_fee)}\n` +
        remarkText,
        'LiuXiaoLin'
      )
      return savedOrder
    })
  }

  // 确认支付（更新菜品销量）
  async confirmPayment(orderId: number, userId: number, status: number | undefined): Promise<OrderEntity> {
    return this.entityManager.transaction(async (manager) => {
      const order = await manager.findOne(OrderEntity, {
        where: { id: orderId, user_id: userId },
        relations: ['items']
      })
      if (!order) {
        throw new HttpException('订单不存在', 404)
      }

      if (order.status !== 0) {
        const statusType = { 0: '待付款', 1: '已付款', 2: '已完成', 3: '退款中', 5: '已退款', 6: '退款驳回' }
        throw new HttpException(`订单当前状态为【${statusType[order.status]}】，无法重复支付`, 409)
      }

      order.status = status ?? 1
      const updatedOrder = await manager.save(OrderEntity, order)

      // 推送企微消息
      const user = await manager.findOne(UserEntity, { where: { id: userId } })
      const nickname = user?.nickname || `用户${userId}`
      const remarkText = updatedOrder.remark ? `\n📝 备注：${updatedOrder.remark}` : ''
      const orderStr = updatedOrder.items.map(item => `${item.menu_name} x${item.quantity}`).join('、')
      const currentTime = getCurrentTime()
      const dinnerType = { 1: '堂食', 2: '外带' }
      await sendWeComMsg(
        `${currentTime} ${nickname}的订单已支付\n` +
        `🧾 订单ID: ${updatedOrder.id}\n` +
        `✅ 状态：已付款\n` +
        `用餐方式：${dinnerType[updatedOrder.dining_method]}\n` +
        `💰 金额：${updatedOrder.total_fee}\n` +
        `🍲 菜品：${orderStr}\n` +
        remarkText +
        `\n请准备~`,
        'LiuXiaoLin'
      )

      // 更新菜品销量
      if (updatedOrder.items && updatedOrder.items.length > 0) {
        const salesMap = new Map<number, number>()
        updatedOrder.items.forEach(item => {
          const currentSales = salesMap.get(item.menu_id) || 0
          salesMap.set(item.menu_id, currentSales + item.quantity)
        })

        // 批量更新销量
        const updatePromises = Array.from(salesMap.entries()).map(async ([menuId, quantity]) => {
          const menu = await manager.findOne(MenuEntity, { where: { id: menuId } })
          if (menu) {
            menu.sales = (menu.sales || 0) + quantity
            await manager.save(MenuEntity, menu)
          }
        })
        await Promise.all(updatePromises)
      }
      return updatedOrder
    })
  }

  // 热门菜品
  async recommendMenu(limit = 6) {
    const topMenus = await this.menuRepository
      .createQueryBuilder('menu')
      .select(['menu.id', 'menu.name', 'menu.fee', 'menu.photo_url'])
      .where('menu.is_del = :is_del', { is_del: 0 })
      .orderBy('menu.sales', 'DESC') // 按销量降序
      .take(limit)
      .getMany()

    if (topMenus.length === 0) {
      return []
    }
    return {
      entries: topMenus
    }
  }
}
